/*
 * 英才汇硕信息科技有限公司 拥有本软件版权 2021 并保留所有权利。
 * Copyright 2021, YCHS Information&Science Techology Co.,Ltd,
 * All right reserved.
 */
package com.ychs.lawyerback.service.impl;

import com.ychs.lawyerback.common.ResultCode;
import com.ychs.lawyerback.dto.MenuOptDTO;
import com.ychs.lawyerback.dto.MenuQueryDTO;
import com.ychs.lawyerback.exception.BussinessException;
import com.ychs.lawyerback.mapper.MenuMapper;
import com.ychs.lawyerback.mapper.UserMapper;
import com.ychs.lawyerback.pojo.MenuEntity;
import com.ychs.lawyerback.pojo.UserEntity;
import com.ychs.lawyerback.service.MenuService;
import com.ychs.lawyerback.vo.MenuQueryVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author mayujing
 * @version 1.0
 */
@Service
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private UserMapper userMapper;


    @Override
    public List<MenuQueryVo> getMenusByUserId(Long userId) {
        //先通过userId找到当前用户的角色id,
        UserEntity userEntity = userMapper.getUserByUserId(userId);
        // 根据角色id找到该角色有些什么菜单权限
        List<MenuEntity> menus =  menuMapper.getUserByRoleId(userEntity.getRoleId());
          //定义一个menuQueryVoList
        List<MenuQueryVo> menuQueryVoList = new ArrayList<>();
        //把查询到的权限菜单分装到树状结构里
        /**
         * .filter 使用流的形式过滤
         * .sorted 排序  Comparator:比较器   Comparator.comparing()---类名.方法名，是静态方法
         * .forEach 填充 循环子菜单 终止操作
         */
        menus.stream().filter(menu->menu.getParentId()==0)
                .sorted(Comparator.comparing(MenuEntity::getOrderNum))
                .forEach(menu->{
                    //先定义，创建一个menuQueryVo对象
                    MenuQueryVo menuQueryVo = new MenuQueryVo();
                    //把每一个menu拷贝到menuQueryVo对象
                    BeanUtils.copyProperties(menu,menuQueryVo);
                    //找当前menu有权限的子菜单，递归
                    List<MenuQueryVo> subMenus = getChildrenMenus(menus,menuQueryVo);
                    //把查到的子菜单，赋值到SubMenus里面，
                    menuQueryVo.setSubMenus(subMenus);
                    menuQueryVoList.add(menuQueryVo);
                });

        return menuQueryVoList;
    }

    @Override
    public Map<String, Object> getMenuList(MenuQueryDTO queryDTO) {
        List<MenuEntity> menuEntities = menuMapper.getMenuList(queryDTO);
        int total = menuMapper.getMenuCount(queryDTO);

        List<MenuQueryVo> menuVos = menuEntities.stream().map(entity -> {
            MenuQueryVo vo = new MenuQueryVo();
            BeanUtils.copyProperties(entity, vo);
            return vo;
        }).collect(Collectors.toList());

        Map<String, Object> result = new HashMap<>();
        result.put("list", menuVos);
        result.put("total", total);
        return result;
    }

    @Override
    public List<MenuQueryVo> getMenuTree() {
        List<MenuEntity> allMenus = menuMapper.getAllMenus();
        return buildMenuTree(allMenus, 0L);
    }

    private List<MenuQueryVo> buildMenuTree(List<MenuEntity> menus, long parentId) {
        return menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> {
                    MenuQueryVo vo = new MenuQueryVo();
                    BeanUtils.copyProperties(menu, vo);
                    vo.setSubMenus(buildMenuTree(menus, menu.getMenuId()));
                    return vo;
                })
                .collect(Collectors.toList());
    }

    @Override
    public MenuQueryVo getMenuById(Long menuId) {
        MenuEntity entity = menuMapper.getMenuById(menuId);
        if (entity == null) {
            throw new BussinessException(ResultCode.MENU_ERROR);
        }
        MenuQueryVo vo = new MenuQueryVo();
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }

    @Override
    @Transactional
    public int addMenu(MenuOptDTO menuOptDTO) {
        MenuEntity entity = new MenuEntity();
        BeanUtils.copyProperties(menuOptDTO, entity);

        // 设置默认值和创建信息
        entity.setCreateTime(LocalDateTime.now());
        entity.setCreateBy(1L); // 实际应从登录信息获取
        entity.setUpdateTime(LocalDateTime.now());
        entity.setUpdateBy(1L); // 实际应从登录信息获取

        return menuMapper.insertMenu(entity);
    }

    @Override
    @Transactional
    public int updateMenu(MenuOptDTO menuOptDTO) {
        MenuEntity entity = menuMapper.getMenuById(menuOptDTO.getMenuId());
        if (entity == null) {
            throw new BussinessException(ResultCode.MENU_ERROR);
        }

        BeanUtils.copyProperties(menuOptDTO, entity);
        entity.setUpdateTime(LocalDateTime.now());
        entity.setUpdateBy(1L); // 实际应从登录信息获取

        return menuMapper.updateMenu(entity);
    }

    @Override
    @Transactional
    public int deleteMenu(String ids) {
        String[] idArray = ids.split(",");
        for (String id : idArray) {
            Long menuId = Long.parseLong(id);
            if (hasChildMenus(menuId)) {
                throw new BussinessException(ResultCode.MENU_INCLUDE);
            }
        }
        return menuMapper.deleteMenus(ids);
    }

    private boolean hasChildMenus(Long menuId) {
        return menuMapper.countChildMenus(menuId) > 0;
    }

    private List<MenuQueryVo> getChildrenMenus(List<MenuEntity> menus, MenuQueryVo menuQueryVo) {
        List<MenuQueryVo> list1 = new ArrayList<>();
        menus.stream().filter(menu->menu.getParentId().equals(menuQueryVo.getMenuId()))
                .sorted(Comparator.comparing(MenuEntity::getOrderNum))
                .forEach(menu->{
                    //先定义，创建一个menuQueryVo对象
                    MenuQueryVo menuQueryVo1 = new MenuQueryVo();
                    //把每一个menu拷贝到menuQueryVo对象
                    BeanUtils.copyProperties(menu,menuQueryVo1);
                    //找当前menu有权限的子菜单，递归
                    List<MenuQueryVo> childrenMenus = getChildrenMenus(menus,menuQueryVo1);
                    //把查到的子菜单，赋值到SubMenus里面，
                    menuQueryVo1.setSubMenus(childrenMenus);
                    list1.add(menuQueryVo1);
                });
        return list1;
    }
}
